package com.futvan.z.framework.util;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.lang.model.element.Modifier;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;

import com.futvan.z.framework.common.bean.Code;
import com.futvan.z.framework.common.bean.JavaClass;
import com.futvan.z.framework.common.bean.JavaMethod;
import com.futvan.z.framework.common.bean.JavaMethodParameter;
import com.futvan.z.framework.common.bean.JavaVariable;
import com.futvan.z.framework.common.bean.Result;
import com.futvan.z.framework.core.z;
import com.futvan.z.system.zhttpservices.z_http_services;

/**
 * JAVA编辑工作类
 * @author 4223947@qq.com
 *
 */
public class JavaCompilerUtil {

	public static void main(String[] args) throws Exception {
		System.out.println(System.getProperty("java.home"));
	}
	
	/**
	 * 编译Java文件
	 * @param java Java文件
	 * @return
	 */
	public static Result CompileJava(String file_path) {
		Result result = new Result();
		File java = new File(file_path);
		if(java.exists() && java.isFile()) {
			//获取编译使用jar文件目录
			String lib_path = SystemUtil.getRunWebAppPath()+"/WEB-INF/lib";
			//创建编译命令
			String javaHome = System.getProperty("java.home");
			if(z.isNotNull(javaHome)) {
				String dos = "cmd /c "+javaHome.substring(0, javaHome.length()-4)+"/bin/javac -Djava.ext.dirs="+lib_path+" -encoding utf-8 "+file_path;
				//执行命令
				SystemUtil.dos(dos);
				//编译完成后删除java源文件
				FileUtil.deleteDir(new File(file_path));
				result.setCode(Code.SUCCESS);
				result.setMsg("编译完成|"+file_path);
			}else {
				result.setCode(Code.ERROR);
				result.setMsg("编译Java出错|获取java.home路径出错");
			}
		}else {
			result.setCode(Code.ERROR);
			result.setMsg("编译Java出错|未找到要编译的文件目录：【"+file_path+"】");
		}
		return result;
	}
	
	/**
	 * 创建JAVA类文件
	 * @param className 类名
	 * @param packageName 包名
	 * @param importList 引用列表
	 * @param MethodList 方法列表
	 * @param FilePath 文件生成目录
	 * @return Result
	 * @throws Exception
	 */
	public static Result CreateJava(JavaClass jc){
		Result result = new Result();
		if(z.isNotNull(jc.getClassName())) {
			if(z.isNotNull(jc.getPackageName())) {
				try {
					//=======创建代码======================================================================
					StringBuffer code = new StringBuffer();
					//创建包路径
					code.append("package "+jc.getPackageName()+";").append("\r\n");
					code.append("").append("\r\n");
					//创建导入类列表
					for (String importClass : jc.getImportList()) {
						code.append("import "+importClass+";").append("\r\n");
					}
					code.append("").append("\r\n");
					//添加类说明
					if(z.isNotNull(jc.getTitle())) {
						code.append("/**").append("\r\n");
						code.append(" * "+jc.getTitle()).append("\r\n");
						code.append(" */").append("\r\n");
					}
					//创建头
					if(z.isNotNull(jc.getPrefix())) {//添加前缀
						code.append(jc.getPrefix()).append("\r\n");
					}
					code.append("public class "+jc.getClassName());
					//如果继承类不为空，添加继承类
					if(z.isNotNull(jc.getExtendsClass())) {
						code.append(" extends "+jc.getExtendsClass()+" ");
					}
					code.append("{").append("\r\n");
					code.append("").append("\r\n");
					//添加变量
					for (JavaVariable jv : jc.getVariableList()) {
						if(z.isNotNull(jv.getAnnotation())) {
							code.append("	//"+jv.getAnnotation()).append("\r\n");
						}
						if(z.isNotNull(jv.getPrefix())) {//添加前缀
							code.append("	"+jv.getPrefix()).append("\r\n");
						}
						code.append("	"+jv.getModifier()+" "+jv.getType()+" "+jv.getName()+";").append("\r\n");
					}
					code.append("").append("\r\n");
					//创建方法
					for (JavaMethod jm : jc.getMethodList()) {
						if(z.isNotNull(jm.getPrefix())) {//添加前缀
							code.append(jm.getPrefix()).append("\r\n");
						}
						code.append("	"+jm.getModifier()+" "+jm.getIsStatic()+" "+jm.getMethodType()+" "+jm.getName()+"(");
						//添加参数
						for (int i = 0; i < jm.getParameterList().size(); i++) {
							JavaMethodParameter p = jm.getParameterList().get(i);
							if(i!=jm.getParameterList().size()-1) {
								code.append(p.getType()+" "+p.getName()+",");
							}else {
								code.append(p.getType()+" "+p.getName());
							}
						}
						code.append("){").append("\r\n");
						//添加方法代码
						if(z.isNotNull(jm.getCode())) {
							code.append("		"+jm.getCode()).append("\r\n");
						}
						code.append("	}").append("\r\n");
						code.append("").append("\r\n");
					}
					code.append("}").append("\r\n");
					//=============================================================================

					//========生成文件=============================================================
					//获取class相对目录
					if(z.isNull(jc.getFilePath())) {
						jc.setFilePath(SystemUtil.getRunClassPath());
					}
					String java_path = jc.getFilePath()+"/"+jc.getClassName()+".java";
					//创建文件
					FileUtil.createrTXT(java_path,code.toString());
					//===============================================================================
					result.setCode(Code.SUCCESS);
					result.setMsg("OK");
					result.setData(java_path);
				} catch (Exception e) {
					result.setCode(Code.ERROR);
					result.setMsg("创建JAVA文件出错："+e.getMessage());
				}
			}else {
				result.setCode(Code.ERROR);
				result.setMsg("packageName is null");
			}
		}else {
			result.setCode(Code.ERROR);
			result.setMsg("className is null");
		}
		return result;
	}
	
	
	/**
	 * 生成接口处理类并编译
	 * @param cinfo
	 */
	public static void CreateServicesClass(z_http_services s) {
		//class目录
		String service_path = SystemUtil.getRunClassPath()+"com/futvan/z/httpservices";
		FileUtil.mkdirs(service_path);

		//构建引用
		List<String> importList = new ArrayList<String>();
		importList.add("java.util.Map");
		importList.add("java.util.HashMap");
		importList.add("java.util.List");
		importList.add("java.util.ArrayList");
		importList.add("com.futvan.z.framework.core.z");
		importList.add("com.futvan.z.framework.core.SuperAction");
		importList.add("com.futvan.z.framework.common.bean.Code");
		importList.add("com.futvan.z.framework.common.bean.Result");
		importList.add("com.futvan.z.framework.common.service.CommonService");
		importList.add("org.springframework.stereotype.Controller");
		importList.add("org.springframework.web.bind.annotation.RequestParam");
		importList.add("org.springframework.web.bind.annotation.ResponseBody");
		importList.add("org.springframework.web.bind.annotation.RequestMapping");
		importList.add("org.springframework.beans.factory.annotation.Autowired");

		//定义变量
		List<JavaVariable> jvlist = new ArrayList<JavaVariable>();
		JavaVariable jv = new JavaVariable();
		jv.setPrefix("@Autowired");
		jv.setType("CommonService");
		jv.setName("commonService");
		jvlist.add(jv);

		//定义方法
		List<JavaMethod> jmlist = new ArrayList<JavaMethod>();
		JavaMethod jm = new JavaMethod();
		jm.setPrefix("	@RequestMapping(value=\"/"+s.getServiceid()+"\")");//方法前缀
		jm.setMethodType("@ResponseBody Result");//返回类型
		jm.setName("Service"); //方法名称
		jm.setCode(s.getJavainfo());
		//-----定义方法参数
		List<JavaMethodParameter> mplist = new ArrayList<JavaMethodParameter>();
		JavaMethodParameter mp = new JavaMethodParameter();
		mp.setType("@RequestParam HashMap<String, String>");
		mp.setName("bean");
		mplist.add(mp);
		jm.setParameterList(mplist);
		jmlist.add(jm);

		//创建接口文件
		JavaClass jc = new JavaClass();
		jc.setClassName(s.getServiceid()+"HttpService");//类名
		jc.setExtendsClass("SuperAction");
		jc.setTitle(s.getTitle());//标题
		jc.setPrefix("@Controller");
		jc.setPackageName("com.futvan.z.httpservices");
		jc.setImportList(importList);//引用列表
		jc.setVariableList(jvlist);//成员变量列表
		jc.setMethodList(jmlist);//方法列表
		jc.setFilePath(service_path);//文件目录
		Result r = JavaCompilerUtil.CreateJava(jc);
		if(Code.SUCCESS.equals(r.getCode())) {
			//创建成功执行编译
			String java_path = jc.getFilePath()+"/"+jc.getClassName()+".java";
			Result cr = CompileJava(java_path);
			if(Code.ERROR.equals(cr.getCode())) {
				z.Error("生成接口处理类|出错："+r.getMsg());
			}
		}else if(Code.ERROR.equals(r.getCode())){
			z.Error("生成接口处理类|出错："+r.getMsg());
		}
	}

}
